//=======================================================
//  LVDS Data prepare Interface 
//=======================================================
module lvds_prepare(
	// Internal Control Signals //
	input 	wire	          	pclk_0c
    	,input    wire                reset_n
	 ,input    wire     		de_d
	 ,input wire	   		hs_d
	 ,input  wire      		vs_d
	,input wire[7:0] 		r_d0
	,input wire[7:0] 		g_d0
	,input wire[7:0]  		b_d0
	,output wire [11:0] 	data_out_e
	,output wire [11:0] 	data_out_o
	,output wire			hs_d_o
	,output wire			vs_d_o
	,output wire			de_d_o

    
    
);

wire [7:0] r_d, g_d, b_d;
reg       de_d_r00, hs_d_r00, vs_d_r00;
reg [7:0]  r_d_r00,  g_d_r00,  b_d_r00;
reg       de_d_r01, hs_d_r01, vs_d_r01;
reg [7:0]  r_d_r01,  g_d_r01,  b_d_r01;
reg       de_d_r02, hs_d_r02, vs_d_r02;
reg [7:0]  r_d_r02,  g_d_r02,  b_d_r02;
reg [7:0] r_d_r0, g_d_r0, b_d_r0;
reg       de_d_r0, hs_d_r0, vs_d_r0;
reg [7:0] r_d_r1, g_d_r1, b_d_r1;
reg       de_d_r1, hs_d_r1, vs_d_r1;
reg [7:0] r_d_r2, g_d_r2, b_d_r2;
reg       de_d_r2, hs_d_r2, vs_d_r2;
reg       de_d_r3, hs_d_r3, vs_d_r3;
reg [7:0] r_d_r3, g_d_r3, b_d_r3;

reg       de_d_r4, hs_d_r4, vs_d_r4;
reg       de_d_r5, hs_d_r5, vs_d_r5;
reg       de_d_r6, hs_d_r6, vs_d_r6;

reg r_d_r0_eq_FF;
reg g_d_r0_eq_00;
reg b_d_r0_eq_FF;

//reg OLED1_clk1 /* synthesis syn_preserve = 1 */;
//reg OLED1_XVD /* synthesis syn_preserve = 1 */;
//reg OLED2_clk1 /* synthesis syn_preserve = 1 */;
//reg OLED2_XVD /* synthesis syn_preserve = 1 */;
reg [5:0] lv0_rst_cnt;
//reg data_LV0_o;
//reg data_LV0_e;

reg [11:0] hs_cnt;

reg [1:0] de_cnt;
reg [2:0] d_e0, d_e1, d_e2, d_e3, d_e4, d_e5, d_e6, d_e7, d_e8, d_e9, d_e10, d_e11;
reg [2:0] d_o0, d_o1, d_o2, d_o3, d_o4, d_o5, d_o6, d_o7, d_o8, d_o9, d_o10, d_o11;


reg [2:0] d2_e0, d2_e1, d2_e2, d2_e3, d2_e4, d2_e5, d2_e6, d2_e7, d2_e8, d2_e9, d2_e10, d2_e11;
reg [2:0] d2_o0, d2_o1, d2_o2, d2_o3, d2_o4, d2_o5, d2_o6, d2_o7, d2_o8, d2_o9, d2_o10, d2_o11;




//assign r_d = !de_d? 8'hFE : r_d0;
//assign g_d = !de_d? 8'hFE : g_d0;
//assign b_d = !de_d? 8'hFE : b_d0;
assign r_d = r_d0;
assign g_d = g_d0;
assign b_d = b_d0;


always @ *
begin
//   hs_d_o= hs_d_r2  ;
//   vs_d_o =vs_d_r2  ;
//   de_d_o= de_d_r2  ;
//    

end

always @ (posedge pclk_0c or negedge reset_n)
begin
  if(!reset_n) 
	begin
	   r_d_r00 <= 0;
	   g_d_r00 <= 0;
	   b_d_r00 <= 0;
	  de_d_r00 <= 0;
	  hs_d_r00 <= 0;
	  vs_d_r00 <= 0;
	   r_d_r01 <= 0;
	   g_d_r01 <= 0;
	   b_d_r01 <= 0;
	  de_d_r01 <= 0;
	  hs_d_r01 <= 0;
	  vs_d_r01 <= 0;
	   r_d_r02 <= 0;
	   g_d_r02 <= 0;
	   b_d_r02 <= 0;
	  de_d_r02 <= 0;
	  hs_d_r02 <= 0;
	  vs_d_r02 <= 0;
	  	  	  
	  r_d_r0 <= 0;
	  g_d_r0 <= 0;
	  b_d_r0 <= 0;
	  de_d_r0 <= 0;
	  hs_d_r0 <= 0;
	  vs_d_r0 <= 0;	
	  r_d_r1 <= 0;
	  g_d_r1 <= 0;
	  b_d_r1 <= 0;
	  de_d_r1 <= 0;
	  hs_d_r1 <= 0;
	  vs_d_r1 <= 0;
	  r_d_r2 <= 0;
	  g_d_r2 <= 0;
	  b_d_r2 <= 0;
	  de_d_r2 <= 0;
	  hs_d_r2 <= 0;
	  vs_d_r2 <= 0;
	  r_d_r3 <= 0;
	  g_d_r3 <= 0;
	  b_d_r3 <= 0;
	  de_d_r3 <= 0;
	  hs_d_r3 <= 0;
	  vs_d_r3 <= 0;

	  r_d_r0_eq_FF <= 0;
	  g_d_r0_eq_00 <= 0;
	  b_d_r0_eq_FF <= 0;
	  	  	  
	  //OLED1_clk1 <= 0;
	  //OLED1_XVD <= 0;
	  //OLED2_clk1 <= 0;
	  //OLED2_XVD <= 0;
	  lv0_rst_cnt <= 0;
		de_cnt <= 0;
		
		d_e0  <= 0;
		d_e1  <= 0;
		d_e2  <= 0;
		d_e3  <= 0;
		d_e4  <= 0;
		d_e5  <= 0;			
		d_e6  <= 0;
		d_e7  <= 0;
		d_e8  <= 0;
		d_e9  <= 0;
		d_e10  <= 0;
		d_e11  <= 0;				
		d_o0  <= 0;
		d_o1  <= 0;
		d_o2  <= 0;
		d_o3  <= 0;
		d_o4  <= 0;
		d_o5  <= 0;			
		d_o6  <= 0;
		d_o7  <= 0;
		d_o8  <= 0;
		d_o9  <= 0;
		d_o10  <= 0;
		d_o11  <= 0;										
	end 
  else
	  begin
	     r_d_r00 <= !de_d? 0 : r_d;
	     g_d_r00 <= !de_d? 0 : g_d;
	     b_d_r00 <= !de_d? 0 : b_d;	    
	    de_d_r00 <= de_d; 
      hs_d_r00 <= hs_d; 
      vs_d_r00 <= vs_d;
	    r_d_r01 <=   r_d_r00;
	    g_d_r01 <=   g_d_r00;
	    b_d_r01 <=   b_d_r00;	    
	    de_d_r01 <= de_d_r00; 
      hs_d_r01 <= hs_d_r00; 
      vs_d_r01 <= vs_d_r00;      
	    r_d_r02 <= r_d_r01;
	    g_d_r02 <= g_d_r01;
	    b_d_r02 <= b_d_r01;	         
	    de_d_r02 <= de_d_r01; 
      hs_d_r02 <= hs_d_r01; 
      vs_d_r02 <= vs_d_r01;
	    r_d_r0 <= r_d;//r_d_r02;
	    g_d_r0 <= g_d;//g_d_r02;
	    b_d_r0 <= b_d;//b_d_r02;
	    de_d_r0 <= de_d;//de_d_r02;
	    hs_d_r0 <= hs_d;//hs_d_r02;
	    vs_d_r0 <= vs_d;//vs_d_r02;	  
	    
	    r_d_r1 <= r_d;//r_d_r0;
	    g_d_r1 <= g_d;//g_d_r0;
	    b_d_r1 <= b_d;//b_d_r0;
	    de_d_r1 <= de_d;//de_d_r0;
	    hs_d_r1 <= hs_d;//hs_d_r0;
	    vs_d_r1 <= vs_d;//vs_d_r0;
	    //r_d_r1 <= r_d_r0;
	    //g_d_r1 <= g_d_r0;
	    //b_d_r1 <= b_d_r0;
	    //de_d_r1 <= de_d_r0;
	    //hs_d_r1 <= hs_d_r0;
	    //vs_d_r1 <= vs_d_r0;	
	        
	    r_d_r2 <= r_d_r1;
	    g_d_r2 <= g_d_r1;
	    b_d_r2 <= b_d_r1;
	    de_d_r2 <= de_d_r1;
	    hs_d_r2 <= hs_d_r1;
	    vs_d_r2 <= vs_d_r1;
	    r_d_r3 <= r_d_r2;
	    g_d_r3 <= g_d_r2;
	    b_d_r3 <= b_d_r2;	    
	    de_d_r3 <= de_d_r2; 
      hs_d_r3 <= hs_d_r2; 
      vs_d_r3 <= vs_d_r2;	
      de_d_r4 <= de_d_r3; 
      hs_d_r4 <= hs_d_r3; 
      vs_d_r4 <= vs_d_r3;
      de_d_r5 <= de_d_r4; 
      hs_d_r5 <= hs_d_r4; 
      vs_d_r5 <= vs_d_r4;
      de_d_r6 <= de_d_r5; 
      hs_d_r6 <= hs_d_r5; 
      vs_d_r6 <= vs_d_r5;
          

      r_d_r0_eq_FF <= r_d == 8'hFF;
      g_d_r0_eq_00 <= g_d == 8'h00;
      b_d_r0_eq_FF <= b_d == 8'hFF;
      
	    //OLED1_clk1 <= hs_d_r2;//hs_d_r6;//hs_d_r0;//hs_d_r1;//hs_d;//hs_d_r2;  --> all OK, it means XVD/clk1's timing is not important
      //OLED1_XVD  <= vs_d_r2;//vs_d_r6;//vs_d_r0;//vs_d_r1;//vs_d;//vs_d_r2;  --> all OK, it means XVD/clk1's timing is not important
	    //OLED2_clk1 <= hs_d_r2;//hs_d_r6;//hs_d_r0;//hs_d_r1;//hs_d;//hs_d_r2;  --> all OK, it means XVD/clk1's timing is not important
      //OLED2_XVD  <= vs_d_r2;//vs_d_r6;//vs_d_r0;//vs_d_r1;//vs_d;//vs_d_r2;  --> all OK, it means XVD/clk1's timing is not important
	    
	    if (!hs_d_r1 && hs_d)
	       hs_cnt <= 0;
	    else   
	       hs_cnt <= hs_cnt + 1;
	    
	    if (!hs_d_r2 && hs_d_r1) //one cycle early (hs-de = 192 (=64*3) cycles) --> OK
	    //if (!de_d_r2 && de_d_r1) //one cycle early                            --> OK
	    //if (!de_d_r0 && !de_d_r1 && r_d_r0_eq_FF && g_d_r0_eq_00 && b_d_r0_eq_FF)  --> OK 	    
	    //if (!de_d && !de_d_r1 && r_d == 8'hFF) // && g_d == 8'h00 && b_d == 8'hFF) --> OK
	       de_cnt <= 0;
	    else if (de_cnt == 2)
	       de_cnt <= 0;
	    else   
	       de_cnt <= de_cnt + 1;
	    
	    //The correct display depends on LV0 RST's timing, i.e., the first cycle of LV0 RST is 38th cycle while the first pixel is 192th cycle      
	    if (!hs_d_r2)  
	    //if (!hs_d_r1)
	       lv0_rst_cnt <= 0;
	    else if (lv0_rst_cnt !== 41)
	    //else if (lv0_rst_cnt !== 42)
	       lv0_rst_cnt <= lv0_rst_cnt + 1;    
	    
		  if (lv0_rst_cnt == 38 || lv0_rst_cnt == 39 || lv0_rst_cnt == 40)
		  //if (lv0_rst_cnt == 39 || lv0_rst_cnt == 40 || lv0_rst_cnt == 41)  
		  		d_e0 <= 3'b001;
		  else if (!de_d_r2)
		     	d_e0 <= 3'b000;			
		  else if (de_cnt == 0)
		  		d_e0 <= {r_d_r2[6],r_d_r2[4],r_d_r2[2]};   
		  else
		      d_e0 <= {1'b0, d_e0[2:1]};		
		      
		  if (lv0_rst_cnt == 38 || lv0_rst_cnt == 39 || lv0_rst_cnt == 40)
		  //if (lv0_rst_cnt == 39 || lv0_rst_cnt == 40 || lv0_rst_cnt == 41)
		  		d_o0 <= 3'b001;  
		  else if (!de_d_r2)
		     	d_o0 <= 3'b000;	
		  else if (de_cnt == 0)
		  		d_o0 <= {r_d_r2[7],r_d_r2[5],r_d_r2[3]};
		  else
		      d_o0 <= {1'b0, d_o0[2:1]};		
		      
		  if (de_cnt == 0) begin
		  		d_e1  <= {g_d_r2[6],g_d_r2[4],g_d_r2[2]};
		  		d_e2  <= {b_d_r2[6],b_d_r2[4],b_d_r2[2]};
		  		d_e3  <= {b_d_r2[0],g_d_r2[0],r_d_r2[0]};
		  		d_e4  <= {r_d_r1[6],r_d_r1[4],r_d_r1[2]};
		  		d_e5  <= {g_d_r1[6],g_d_r1[4],g_d_r1[2]};
		  		d_e6  <= {b_d_r1[6],b_d_r1[4],b_d_r1[2]};
		  		d_e7  <= {b_d_r1[0],g_d_r1[0],r_d_r1[0]};
		  		d_e8  <= {r_d[6],r_d[4],r_d[2]};
		  		d_e9  <= {g_d[6],g_d[4],g_d[2]};
		  		d_e10 <= {b_d[6],b_d[4],b_d[2]};
		  		d_e11 <= {b_d[0],g_d[0],r_d[0]};		
		  end else begin
		      d_e1  <= {1'b0, d_e1[2:1]};		    
		      d_e2  <= {1'b0, d_e2[2:1]};	
          d_e3  <= {1'b0, d_e3[2:1]};		    
		      d_e4  <= {1'b0, d_e4[2:1]};
		      d_e5  <= {1'b0, d_e5[2:1]};		    
		      d_e6  <= {1'b0, d_e6[2:1]};
		      d_e7  <= {1'b0, d_e7[2:1]};		    
		      d_e8  <= {1'b0, d_e8[2:1]};
		      d_e9  <= {1'b0, d_e9[2:1]};		    
		      d_e10 <= {1'b0, d_e10[2:1]};   
		      d_e11 <= {1'b0, d_e11[2:1]};
		  end    
		  
		  if (de_cnt == 0) begin                          
		  		d_o1  <= {g_d_r2[7],g_d_r2[5],g_d_r2[3]};            
		  		d_o2  <= {b_d_r2[7],b_d_r2[5],b_d_r2[3]};            
		  		d_o3  <= {b_d_r2[1],g_d_r2[1],r_d_r2[1]};  
		  		d_o4  <= {r_d_r1[7],r_d_r1[5],r_d_r1[3]};   
		  		d_o5  <= {g_d_r1[7],g_d_r1[5],g_d_r1[3]};   
		  		d_o6  <= {b_d_r1[7],b_d_r1[5],b_d_r1[3]};   
		  		d_o7  <= {b_d_r1[1],g_d_r1[1],r_d_r1[1]};   
		  		d_o8  <= {r_d[7],r_d[5],r_d[3]};   
		  		d_o9  <= {g_d[7],g_d[5],g_d[3]};   
		  		d_o10 <= {b_d[7],b_d[5],b_d[3]};   
		  		d_o11 <= {b_d[1],g_d[1],r_d[1]};	
		  end else begin                                  
		      d_o1  <= {1'b0, d_o1[2:1]};		              
		      d_o2  <= {1'b0, d_o2[2:1]};	                
          d_o3  <= {1'b0, d_o3[2:1]};		              
		      d_o4  <= {1'b0, d_o4[2:1]};                 
		      d_o5  <= {1'b0, d_o5[2:1]};		              
		      d_o6  <= {1'b0, d_o6[2:1]};                 
		      d_o7  <= {1'b0, d_o7[2:1]};		              
		      d_o8  <= {1'b0, d_o8[2:1]};                 
		      d_o9  <= {1'b0, d_o9[2:1]};		              
		      d_o10 <= {1'b0, d_o10[2:1]};                
		      d_o11 <= {1'b0, d_o11[2:1]};                
		  end                                             
		  
	  end
end


assign data_out_e = {d_e11[0],d_e10[0],d_e9[0],d_e8[0],d_e7[0],d_e6[0],d_e5[0],d_e4[0],d_e3[0],d_e2[0],d_e1[0],d_e0[0]};
assign data_out_o = {d_o11[0],d_o10[0],d_o9[0],d_o8[0],d_o7[0],d_o6[0],d_o5[0],d_o4[0],d_o3[0],d_o2[0],d_o1[0],d_o0[0]};
assign hs_d_o= hs_d_r2  ;
assign   vs_d_o =vs_d_r2  ;
assign   de_d_o= de_d_r2  ;
	
endmodule

